// File: dao/NovelDao.cpp
#include "noveldao.h"

NovelDao::NovelDao(QObject *parent) : QObject(parent) {}

int NovelDao::queryCount(const QList<QString> &idList){
    QSqlQuery query;

    //参数占位符
    QStringList placeholders;

    // 2. 生成IN子句的参数占位符（避免SQL注入）
    for (int i = 0; i < idList.size(); ++i) {
        placeholders << QString(":id%1").arg(i);
    }


    // 修正后的插入sql
    QString sql = QString("SELECT COUNT(DISTINCT id) "
                  "FROM novel_info "
                  "WHERE id IN (%1)").arg(placeholders.join(", "));

    query.prepare(sql);

    // 绑定每个id到对应的占位符
    for (int i = 0; i < idList.size(); ++i) {
        // idList是QString*的列表，需要解引用获取实际字符串
        query.bindValue(QString(":id%1").arg(i), idList[i]);
    }

    // 执行查询并处理结果
    if (query.exec()) {
        if (query.next()) { // 获取第一条结果（COUNT的结果）
            return query.value(0).toInt(); // 第一列就是计数结果
        }
    } else {
        // 输出错误信息便于调试
        qDebug() << "查询数量失败，错误:" << query.lastError().text();
        qDebug() << "失败语句:" << query.lastQuery();
    }

    // 出错时返回0
    return 0;
}

//新增
bool NovelDao::insert(NovelInfo *novel) {
    QSqlQuery query;


    // 修正后的插入sql
    QString sql = "INSERT INTO novel_info (id, title, author, cover_path, description, category, tags, language, status, chapters_count, word_count, last_read_chapter, source_type, source_url) "
                  "VALUES (:id, :title, :author, :cover_path, :description, :category, :tags, :language, :status, :chapters_count, :word_count, :last_read_chapter, :source_type, :source_url);";
    query.prepare(sql);
    qDebug() << "Prepared SQL statement:" << sql;

    // 绑定数值
    query.bindValue(":id", novel->getId());
    query.bindValue(":title", novel->getTitle());
    query.bindValue(":author", novel->getAuthor());
    query.bindValue(":cover_path", novel->getCoverPath());
    query.bindValue(":description", novel->getDescription());
    query.bindValue(":category", novel->getCategory());
    query.bindValue(":tags", novel->getTags());
    query.bindValue(":language", novel->getLanguage());
    query.bindValue(":status", novel->getStatus());
    query.bindValue(":chapters_count", novel->getChaptersCount());
    query.bindValue(":word_count", novel->getWordCount());
    query.bindValue(":last_read_chapter", novel->getLastReadChapter());
    query.bindValue(":source_type", novel->getSourceType());
    query.bindValue(":source_url", novel->getSourceUrl());

    // 执行插入
    if (query.exec()) {
        qDebug() << "插入小说信息成功：" << query.lastInsertId();
        return true;
    } else {
        qDebug() << "插入小说信息失败，信息:" << query.lastError().text();
        qDebug() << "失败语句:" << query.lastQuery();
        return false;
    }
}


bool NovelDao::update(NovelInfo *novel) {
    if (!novel) {
        qDebug() << "更新失败：novelInfo为空";
        return false;
    }

    QSqlQuery query;
    QList<QString> setClauses; // 存储需要更新的字段子句（如 "title = :title"）
    QVariantMap params;       // 存储需要绑定的参数（键：占位符，值：字段值）

    // 获取小说ID（WHERE条件，必须存在）
    const QString novelId = novel->getId();
    if (novelId.isNull()) {
        qDebug() << "更新失败：小说ID为空";
        return false;
    }
    params[":id"] = novelId; // 绑定WHERE条件的ID


    // -------------------------- 逐个处理所有字段 --------------------------
    // 1. title（TEXT NOT NULL，数据库不允许Null，但若传入Null则不更新）
    const QString title = novel->getTitle();
    if (!title.isNull()) { // 非Null则更新（空字符串视为有效更新）
        setClauses << "title = :title";
        params[":title"] = title;
    }

    // 2. author（TEXT DEFAULT '用户'，Null不更新）
    const QString author = novel->getAuthor();
    if (!author.isNull()) {
        setClauses << "author = :author";
        params[":author"] = author;
    }

    // 3. cover_path（TEXT，Null不更新）
    const QString coverPath = novel->getCoverPath();
    if (!coverPath.isNull()) {
        setClauses << "cover_path = :cover_path";
        params[":cover_path"] = coverPath;
    }

    // 4. description（TEXT，Null不更新）
    const QString description = novel->getDescription();
    if (!description.isNull()) {
        setClauses << "description = :description";
        params[":description"] = description;
    }

    // 5. category（TEXT，Null不更新）
    const QString category = novel->getCategory();
    if (!category.isNull()) {
        setClauses << "category = :category";
        params[":category"] = category;
    }

    // 6. tags（TEXT，Null不更新）
    const QString tags = novel->getTags();
    if (!tags.isNull()) {
        setClauses << "tags = :tags";
        params[":tags"] = tags;
    }

    // 7. language（TEXT DEFAULT 'zh-CN'，Null不更新）
    const QString language = novel->getLanguage();
    if (!language.isNull()) {
        setClauses << "language = :language";
        params[":language"] = language;
    }

    // 8. status（INTEGER DEFAULT 0，-1视为未设置，不更新；其他值更新）
    const int status = novel->getStatus();
    if (status != -1) { // 假设-1是“未设置”的标记（可根据业务调整）
        setClauses << "status = :status";
        params[":status"] = status;
    }

    // 9. chapters_count（INTEGER DEFAULT 0，-1视为未设置）
    const int chaptersCount = novel->getChaptersCount();
    if (chaptersCount != -1) {
        setClauses << "chapters_count = :chapters_count";
        params[":chapters_count"] = chaptersCount;
    }

    // 10. word_count（INTEGER DEFAULT 0，-1视为未设置）
    const int wordCount = novel->getWordCount();
    if (wordCount != -1) {
        setClauses << "word_count = :word_count";
        params[":word_count"] = wordCount;
    }

    // 11. publish_time（TEXT DEFAULT CURRENT_TIMESTAMP，Null不更新）
    const QString publishTime = novel->getPublishTime();
    if (!publishTime.isNull()) {
        setClauses << "publish_time = :publish_time";
        params[":publish_time"] = publishTime;
    }

    // 12. create_time（创建时间，通常不更新，除非有特殊需求）
    const QString createTime = novel->getCreateTime();
    if (!createTime.isNull()) { // 若业务需要更新创建时间，取消注释
        setClauses << "create_time = :create_time";
        params[":create_time"] = createTime;
    }

    // 13. update_time（更新时间，建议强制更新为当前时间）
    const QString updateTime = novel->getUpdateTime();
    setClauses << "update_time = :update_time"; // 无论是否传入，强制更新为当前时间
    params[":update_time"] = updateTime;

    // 14. last_read_chapter（TEXT，Null不更新）
    const QString lastReadChapter = novel->getLastReadChapter();
    if (!lastReadChapter.isNull()) {
        setClauses << "last_read_chapter = :last_read_chapter";
        params[":last_read_chapter"] = lastReadChapter;
    }

    // 15. file_size（INTEGER DEFAULT 0，-1视为未设置）
    const qint64 fileSize = novel->getFileSize();
    if (fileSize != -1) {
        setClauses << "file_size = :file_size";
        params[":file_size"] = fileSize;
    }

    // 16. source_type（INTEGER DEFAULT 0，-1视为未设置）
    const int sourceType = novel->getSourceType();
    if (sourceType != -1) {
        setClauses << "source_type = :source_type";
        params[":source_type"] = sourceType;
    }

    // 17. source_url（TEXT，Null不更新）
    const QString sourceUrl = novel->getSourceUrl();
    if (!sourceUrl.isNull()) {
        setClauses << "source_url = :source_url";
        params[":source_url"] = sourceUrl;
    }

    // 18. parse_progress（REAL DEFAULT 0.0，-1.0视为未设置）
    const double parseProgress = novel->getParseProgress();
    if (parseProgress >= 0) { // 进度范围通常是0~100，-1视为未设置
        setClauses << "parse_progress = :parse_progress";
        params[":parse_progress"] = parseProgress;
    }


    // -------------------------- 执行更新逻辑 --------------------------
    // 无字段需要更新时，直接返回成功
    if (setClauses.isEmpty()) {
        qDebug() << "无需更新（ID：" << novelId << "）：所有字段均为无效值";
        return true;
    }

    // 构建完整SQL
    const QString sql = QString("UPDATE novel_info SET %1 WHERE id = :id")
                            .arg(setClauses.join(", "));

    // 绑定参数并执行
    query.prepare(sql);
    for (const auto &key : params.keys()) {
        query.bindValue(key, params[key]);
    }

    if (query.exec()) {
        qDebug() << "更新成功（ID：" << novelId << "），更新字段数：" << setClauses.size();
        return true;
    } else {
        qDebug() << "更新失败（ID：" << novelId << "），错误：" << query.lastError().text();
        qDebug() << "执行SQL：" << query.lastQuery();
        return false;
    }
}


bool NovelDao::deleteNovel(const QString & novelId){
    QSqlQuery query;

    query.prepare("DELETE FROM novel_info WHERE id = :id");
    query.bindValue(":id", novelId);

    if (!query.exec()) {
        qWarning() << "Delete novel failed:" << query.lastError().text();
        return false;
    }

    return true;
}

NovelInfo* NovelDao::getNovelById(const QString & novelId)
{
    QSqlQuery query;


    query.prepare("SELECT * FROM novels WHERE id = :id");
    query.bindValue(":id", novelId);

    if (!query.exec() || !query.next()) {
        return nullptr;
    }

    NovelInfo *novel = new NovelInfo();
    novel->setId(query.value("id").toString());
    novel->setTitle(query.value("title").toString());
    novel->setCoverPath(query.value("cover_path").toString());
    novel->setStatus(query.value("status").toInt());

    return novel;
}


QList<QObject*> NovelDao::findAll() {
    QList<QObject*> novelList;

    //执行sql
    QSqlQuery query("SELECT id,title,cover_path,status FROM novel_info ORDER BY update_time DESC,title");

    //组装结果
    while (query.next()) {
        NovelInfo *novel = new NovelInfo;
        novel->setId(query.value("id").toString());
        novel->setTitle(query.value("title").toString());
        novel->setCoverPath(query.value("cover_path").toString());
        novel->setStatus(query.value("status").toInt());

        qDebug() << "书架对象是：" << novel->getTitle();

        novelList.append(novel);
    }

    return novelList;
}

// 其他方法实现类似...
